#pragma once
#include "Socket.hpp"
#include <iostream>
#include <memory>
#include <sys/epoll.h>

class EpollServer
{
    static const int gnum = 5;

private:
    void Accepter()
    {
        InetAddr addr;
        int fd = _listensock->Accepter(&addr);//获得新fd
        if(fd < 0)
        {
            LOG(ERROR, "获取连接失败\n");
            return;
        }
        //加入监视
        struct epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.fd = fd;
        ::epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev);
        LOG(INFO, "epoll_ctl success, add new sockfd : %d\n", fd);
    }
    void HandlerIO(int fd)
    {
        char inbuffer[1024];
        int n = recv(fd, inbuffer, sizeof(inbuffer) - 1, 0);
        if (n > 0)
        {
            inbuffer[n] = 0;
            std::cout << inbuffer;
            std::string response = "HTTP/1.0 200 OK\r\n";
            std::string content = "<html><body><h1>hello bite, hello world</h1></body></html>";
            response += "Content-Type: text/html\r\n";
            response += "Content-Length: " + std::to_string(response.size()) + "\r\n";
            content += "\r\n";
            content += response;
        }
        else if (n == 0)
        {
            LOG(INFO, "client quit, close fd: %d\n", fd);
            // 1. 从epoll中移除, 从epoll中移除fd，这个fd必须是健康&&合法的fd. 否则会移除出错
            ::epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, nullptr);
            // 2. 关闭fd
            ::close(fd);
        }
        else
        {
            LOG(ERROR, "recv error, close fd: %d\n", fd);
            // 1. 从epoll中移除, 从epoll中移除fd，这个fd必须是健康&&合法的fd. 否则会移除出错
            ::epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, nullptr);
            // 2. 关闭fd
            ::close(fd);
        }
    }
    void HandlerEvent()
    {
        for (int i = 0; i < gnum; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            if (revents & EPOLLIN)//就绪队列里就绪状态
            {
                if (fd == _listensock->Sockfd())
                    Accepter();
                else
                    HandlerIO(fd);
            }
        }
    }

public:
    EpollServer(uint16_t port)
        : _listensock(std::make_unique<Socket>()), _port(port)
    {
        _listensock->BuildClientSocket("82.156.214.185", port);
        // 创建epoll模型
        _epollfd = epoll_create(gnum);
        if (_epollfd < 0)
        {
            LOG(FATAL, "epoll_create error!\n");
            exit(1);
        }
        LOG(INFO, "epoll create success, epfd: %d\n", _epollfd);
    }
    void Init()
    {
        // 添加到红黑树中
        struct epoll_event ev;
        // 事件
        ev.events = EPOLLIN;
        // fd
        ev.data.fd = _listensock->Sockfd();
        int n = epoll_ctl(_epollfd, EPOLL_CTL_ADD, _listensock->Sockfd(), &ev);
        if (n < 0)
        {
            LOG(FATAL, "epoll_ctl error!\n");
            exit(2);
        }
        LOG(INFO, "epoll_ctl success, add new sockfd : %d\n", _listensock->Sockfd());
    }
    void Loop()
    {
        while (true)
        {
            int timeout = 3000;
            int n = epoll_wait(_epollfd, _revs, gnum, timeout);
            switch (n)
            {
            case 0:
                LOG(INFO, "epoll time out...\n");
                break;
            case -1:
                LOG(ERROR, "epoll error\n");
                break;
            default:
                LOG(INFO, "haved event happend!, n : %d\n", n);
                // HandlerEvent(n);
                break;
            }
        }
    }

private:
    int _epollfd;
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;
    struct epoll_event _revs[gnum];
};